// 特点一： 在块级作用域内声明有效，外部无法访问

// if(true){
//     var a = 'a'
//     let b = 'b'
// }
// console.log(a) // a —— var声明后相当于全局变量, 在全局内都可访问
// console.log(b)  // undefind —— let声明后只在if的块级作用域内有效


// -----------------------  
// 特点二： 即使是同名变量，也只在该声明变量的作用域内有效， 能够有效地防止因为变量重名导致的错误

// for(var i = 0 ; i < 3; i++){
//     for(var i = 0 ; i < 3; i++){
//         console.log(i) // 1 2 3
//     }
//     console.log('内层结束 i='+i) // 3
// } 
// var是定义的变量是一个全局变量，当内层再定一个i的时候， 
// 内层的i会将外层的i覆盖，当执行完内部的循环后， 才会把i赋值给外层的i
 
// for(let i = 0 ; i < 3; i++){
//     for(let i = 0 ; i < 3; i++){
//         console.log(i) // 1 2 3
//     }
//     console.log('内层结束 i='+i) // 1 2 3
// }
// 内层的i使用的是内层定一个的i，而且不会覆盖外层的i
// let可以解决作用域内重名的问题
// 一般情况下， 循环嵌套内的变量名尽量不要重名

//  ------------------------ 


// var elements = [{}, {}, {}]
// for(var i = 0 ; i < elements.length; i++){
//     elements[i].onclick = () =>{
//         console.log(i)
//     }
// }
// elements[2].onclick()
// 当elements设置的角标为0/1/2时，打印的结果都是3
// 是因为i被定义为全局的变量，全局变量的结果只有在循环结束后才会把最终的值赋值给i
// 所以此时i的值始终为3


// var elements = [{}, {}, {}]
// for(var i = 0 ; i < elements.length; i++){
//     elements[i].onclick = ((i) =>{
//         return ()=>{
//             console.log(i)
//         }
//     })(i)
// }
// elements[1].onclick()
// 通过闭包的产生的局部作用域来摆脱全局作用域的影响


// var elements = [{}, {}, {}]
// for(let i = 0 ; i < elements.length; i++){
//     elements[i].onclick = () =>{
//         console.log(i)
//     }
// }
// elements[0].onclick()
// 通过let来声明块级作用域的变量，使i只能在块级作用域内被访问  

//————————————————————  
// let不允许变量提升

// console.log(f)
// var f = 'foo' // foo
// console.log(b)
// let b = 'bar' // undefined